
Imports MathNet.Numerics.Statistics

Namespace Aricie.DNN.Caching.Analysis
    Public Class StatisticsEngine(Of T)

        Private _ImportConverter As Converter(Of T, Double)
        Private _ExportConverter As Converter(Of Double, T)

        Private _Accumulator As Accumulator
        Private Shared maxIntAsDouble As Double = CDbl(Integer.MaxValue)


        Public Sub New(ByVal importConverter As Converter(Of T, Double), ByVal exportConverter As Converter(Of Double, T))
            _ImportConverter = importConverter
            _ExportConverter = exportConverter

        End Sub

        Public Sub ComputeStats(ByRef objSeries As Series(Of T))
            If objSeries.Items.Count > 0 Then
                Dim convertedItems As New Aricie.Collections.ConvertedEnumerable(Of T, Double)(objSeries.Items, Me._ImportConverter)

                Dim tempAccumulator As New Accumulator(convertedItems)
                Dim dblMean As Double = tempAccumulator.Mean
                objSeries.Mean = Me._ExportConverter.Invoke(dblMean)
                Dim dblEE As Double = tempAccumulator.ErrorEstimate
                If Not Double.IsNaN(dblEE) Then
                    Dim absMean As Double = Math.Abs(dblMean)
                    If absMean > Double.Epsilon Then
                        objSeries.CoefOfVariation = Convert.ToInt32((tempAccumulator.Sigma / absMean) * 100.0)
                    Else
                        objSeries.CoefOfVariation = -1
                    End If
                Else
                    objSeries.CoefOfVariation = -1
                End If


                'Dim absMean As Decimal = CDec(Math.Abs(dblMean))
                'If absMean > Double.Epsilon Then
                '    objSeries.RelativeStandardError = CInt((CDec(tempAccumulator.ErrorEstimate) / absMean) * 100.0)
                'Else
                '    objSeries.RelativeStandardError = 100
                'End If
            Else
                objSeries.Mean = Me._ExportConverter.Invoke(0.0)
            End If


        End Sub

        Public Sub MergeSeries(ByRef seriesToUpdate As Series(Of T), ByVal seriesToAdd As Series(Of T))
            seriesToUpdate.Items.AddRange(seriesToAdd.Items)
            ComputeStats(seriesToUpdate)
        End Sub



    End Class
End Namespace